﻿// Lesson24.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include "pch.h"
#include <iostream>
#include <ratio>
#include <chrono>
#include <time.h>
#include <iomanip>
#include <random>
#include <functional>
#include <optional>
#include <variant>
#include <any>
#include <tuple>
#include <string>
#include <algorithm>
#include <filesystem>

int get_random_between(int min, int max)
{
	return (rand() % (max + 1 - min)) + min;
}

std::optional<int> getInt(const std::string& str)
{
	try {
		return std::stoi(str);
	}
	catch (...)
	{
		return {};
	}
}

struct Foo
{
	int mInt;
	std::string mString;
	bool mBool;

	Foo(int i, std::string& s, bool b)
		:mInt(i), mString(s), mBool(b)
	{

	}
};

bool operator <(const Foo& f1, const Foo& f2)
{
	return std::tie(f1.mInt,f1.mString,f1.mBool ) < std::tie(f2.mInt, f2.mString, f2.mBool);
}

int main()
{
	using r1 = std::ratio<1,60>; //1/60 编译期
	intmax_t num = r1::num;//分子
	intmax_t den = r1::den;//分母

	//std::chrono::duration<long/*,std::ratio<1,1>*/> d1;//默认以1秒为周期

	//std::chrono::duration<long, std::ratio<60> > d2;//60秒为周期的duration

	//std::chrono::duration<long, std::ratio<1,60> > d3;//60秒为周期的duration

	//std::chrono::duration<long long, std::milli> d4;//毫秒为周期

	std::chrono::duration<long, std::ratio<60> > d1(123);//123分钟

	std::cout << d1.count() << std::endl;

	std::chrono::duration<long> d2(d1);

	std::cout << d2.count() << std::endl;

	std::chrono::duration<long> d3(20);

	std::chrono::duration<double, std::ratio<60> > d4 = d1 + d3;
	std::chrono::duration<long, std::ratio<1> > d5 = d1 + d3;
	std::cout << d5.count() << std::endl;

	std::chrono::duration<long> d7(30);
	std::chrono::duration<long, std::ratio<60> > d8=
		std::chrono::duration_cast<std::chrono::duration<long, std::ratio<60> > >(d7);

	std::chrono::minutes min9(9);//9min
	std::chrono::seconds secs(9);//9s
	std::chrono::milliseconds milli(9);//9 milliseconds

	auto t = std::chrono::hours(1) + std::chrono::minutes(35) + std::chrono::seconds(49);
	std::cout << t.count() << std::endl;

	//h,min,s,ms,us,ns
	using namespace std::chrono;
	auto td = 42min + 36s;
	std::cout << td.count() << std::endl;

	std::chrono::system_clock::time_point tnow = std::chrono::system_clock::now();

	time_t nowt = time(NULL);
	std::chrono::system_clock::time_point ctnow = std::chrono::system_clock::from_time_t(nowt);

	time_t tpnow = std::chrono::system_clock::to_time_t(ctnow);

	struct tm* tmnow = localtime(&nowt);
	//struct tm tmnow = {0};
	//localtime(&tmnow, &nowt);
	std::cout << std::put_time(tmnow, "%H:%M:%S") << std::endl;

	//strftime
	char buffer[80] = {0};
	strftime(buffer, sizeof(buffer), "%H:%M:%S",tmnow);

	std::chrono::high_resolution_clock::time_point tpbegin = std::chrono::high_resolution_clock::now();

	double x = 0;
	for (size_t i = 0; i < 100000; i++)
	{
		x += i;
	}

	std::chrono::high_resolution_clock::time_point tpend = std::chrono::high_resolution_clock::now();

	std::cout<<std::chrono::duration_cast<std::chrono::duration<double, std::milli>>(tpend - tpbegin).count() << std::endl;;

	tpbegin.time_since_epoch();


	std::random_device seeder;
	const auto seed = seeder.entropy() ? seeder():time(nullptr);
	std::mt19937 eng(static_cast<std::mt19937::result_type>(seed));

	std::uniform_int_distribution<int> dist(1, 99);

	std::cout << dist(eng) << std::endl;

	auto gen = std::bind(dist, eng);

	std::vector<int> vec(10);

	std::generate(std::begin(vec),std::end(vec),gen);

	for (size_t i = 0; i < vec.size(); i++)
	{
		std::cout << vec[i] << " ";
	}
	std::cout << std::endl;
	std::optional<int> op1 = getInt("123");
	if (op1.has_value())
	{
		std::cout << "123=" << op1.value() << std::endl;
	}

	std::optional<int> op2 = getInt("abc");
	if (op2.has_value())
	{
		std::cout << "abc=" << op2.value() << std::endl;
	}

	//union MyUnion
	//{
	//	int i;
	//	char c;
	//	std::string str;
	//	double d;
	//};

	std::variant<int, char, std::string, double> v;
	v = 23;
	v = 'a';
	v = "ABC";
	//v = 29.118;

	std::get<std::string>(v);
	std::string* strptr = std::get_if<std::string>(&v);

	std::any empty;
	std::any intany(2019);
	std::any strany(std::string("str"));

	intany.has_value();

	std::any_cast<int>(intany);

	//std::pair
	std::tuple<int, double, char, std::string, std::vector<int> > mytuple;



	std::get<0>(mytuple);

	using MyTupleType = std::tuple<int, std::string, bool>;
	MyTupleType MyTuple(16,"abc",true);

	std::get<1>(MyTuple) = "XYZ";
	std::cout << std::get<1>(MyTuple) << std::endl;

	std::string s =std::get<std::string>(MyTuple);
	
	std::cout << std::tuple_size<decltype(MyTuple)>::value << std::endl;

	std::tuple t1(32, std::string("abc"), false);

	std::tuple t2(39, std::ref(s), std::cref(v));//tuple<int,std::string&,std::variant<int, char, std::string, double>&>

	auto t3 = std::make_tuple(32, std::string("abc"), false);

	//获取元组的所有部分-> 分解
	//auto[ival, sval, bval] = t3;

	int ival;
	std::string sval;
	bool bval;
	std::tie(ival,sval,bval) = t3;
	std::tie(ival, std::ignore, bval) = t3;

	//串联
	auto t4 = std::tuple_cat(mytuple,t3);

	auto foo =std::make_from_tuple<Foo>(t3);

	std::apply(std::plus<int>(),std::make_tuple(39,2));

	std::filesystem::path p1(R"(D:\Foo\bar)");
	std::filesystem::path p2("/usr/local/bin");
	auto subp1 = p1 / "abc";//D:\Foo\bar\abc
	auto extp1 = p1.concat("abc");//D:\Foo\barabc

	//subp1.remove_filename();

	std::filesystem::directory_entry dirEntry(subp1);
	
	auto begin = std::filesystem::directory_iterator(p1);
	auto end = std::filesystem::directory_iterator();
	for (auto iter= begin; iter!=end;++iter)
	{
		auto& entry = *iter;
		if (entry.is_regular_file())
		{
			//...普通文件
		}
		else if (entry.is_directory())
		{
			//是一个目录

		}
	}

	return 0;
}

// 运行程序: Ctrl + F5 或调试 >“开始执行(不调试)”菜单
// 调试程序: F5 或调试 >“开始调试”菜单

// 入门提示: 
//   1. 使用解决方案资源管理器窗口添加/管理文件
//   2. 使用团队资源管理器窗口连接到源代码管理
//   3. 使用输出窗口查看生成输出和其他消息
//   4. 使用错误列表窗口查看错误
//   5. 转到“项目”>“添加新项”以创建新的代码文件，或转到“项目”>“添加现有项”以将现有代码文件添加到项目
//   6. 将来，若要再次打开此项目，请转到“文件”>“打开”>“项目”并选择 .sln 文件
